#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include "cJSON.h"
#include "msgheader.h"
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include "shmem.h"
#include "msg_queue_peer.h"
#include <sys/epoll.h>
#include <poll.h>

//可以删除
union value {
    BOOL a_val;
    int b_val;
    float c_val;
};

struct stm32_node
{
    int key;             //唯一键值
    char name[32];       //设备名
    int type;            //数据点类型
    int dev_type;        //数据点属于那个设备，根据网关支持的设备自行定义
    union value old_val; //变化上报后需要更新旧值
    union value new_val; //新值
    int ret;             //  默认为-1,采集成功后设置为0,采集失败后再置-1
};

// struct msgbuf
// {
//     long mtype;
//     char mdata[64];
// };
struct msgbuf recv_buf;
static struct shm_param para;
static int *total;                  //指向共享内存中数据节点总个数
static struct stm32_node *node_arr; //指向共享内存中节点缓存数组头
#define MAX_NODE 128                //最大支持学生数目，实际可用是127
#define STD_NODE_LEN sizeof(struct stm32_node)
#define MAX_NODE_SIZE (MAX_NODE * STD_NODE_LEN)
int G;
void *handler(void *arg)
{
    // 创建结构体数组并初始化
    struct stm32_node stm32[] = {
        {0, "heating", 1, 1, 0, 0, -1},
        {1, "cooling", 1, 1, 0, 0, -1},
        {2, "chushi", 1, 1, 0, 0, -1},
        {3, "temperature", 3, 1, 0, 0, -1},
        {4, "humidity", 3, 1, 0, 0, -1}};

    struct stm32_node node;
    char buf[128];
    int acceptfd = (*(int *)arg); // 4     5
    while (1)
    {
        int recvbyte = recv(acceptfd, buf, sizeof(buf), 0);
        if (recvbyte < 0)
        {
            perror("recv is err:");
            return NULL;
        }
        else if (recvbyte == 0)
        {
            printf("client si exit\n");
            close(acceptfd);
            break;
        }
        else
        {
            // if (node.dev_type == 1)
            // {

            printf("client: %s\n", buf);
            //从单片机获取的JSON转数据
            //反序列化json
            cJSON *root = cJSON_Parse(buf);
            if (NULL == root)
            {
                printf("parse err\n");
                return 0;
            }
            // //获取root节点上的item0节点
            // cJSON *item0 = cJSON_GetObjectItem(root, "light");
            // printf("%s = %d\n", item0->string, item0->valueint);
            // stm32[0].new_val.a_val = item0->valueint;
            //获取root节点上的item1节点
            cJSON *item1 = cJSON_GetObjectItem(root, "heating");
            printf("%s = %d\n", item1->string, item1->valueint);
            stm32[0].new_val.a_val = item1->valueint;
            //获取root节点上的item2节点
            cJSON *item2 = cJSON_GetObjectItem(root, "cooling");
            printf("%s = %d\n", item2->string, item2->valueint);
            stm32[1].new_val.a_val = item2->valueint;
            //获取root节点上的item3节点
            cJSON *item3 = cJSON_GetObjectItem(root, "chushi");
            printf("%s = %d\n", item3->string, item3->valueint);
            stm32[2].new_val.a_val = item3->valueint;
            //获取root节点上的item4节点
            cJSON *item4 = cJSON_GetObjectItem(root, "temperature");
            printf("%s = %.2f\n", item4->string, item4->valuedouble);
            stm32[3].new_val.c_val = item4->valuedouble;
            //获取root节点上的item5节点
            cJSON *item5 = cJSON_GetObjectItem(root, "humidity");
            printf("%s = %.2f\n", item5->string, item5->valuedouble);
            stm32[4].new_val.c_val = item5->valuedouble;

            //写共享内存

            int ret = -1;

            ret = shm_init(&para, "shm_test", MAX_NODE_SIZE);
            if (ret < 0)
            {
                struct msgbuf recv_buf;
                return 0;
            }

            void *node_p = shm_getaddr(&para);
            if (node_p == NULL)
            {
                return 0;
            }

            // 4     5
            // while (1)
            // {          //前4个字节存储实际的学生数目
            //total = (int *)node_p;
            //后面空间存储数据点
            node_arr = (struct stm32_node *)(node_p + sizeof(int));

            //*total = 3; //假设有3个人

            //heating赋值
            node_arr[0].new_val.a_val = item1->valueint;
            strcpy(node_arr[0].name, "heating");

            //cooling赋值
            node_arr[1].new_val.a_val = item2->valueint;
            strcpy(node_arr[1].name, "cooling");

            //chushi赋值
            node_arr[2].new_val.a_val = item3->valueint;
            strcpy(node_arr[2].name, "chushi");

            //temperature赋值
            node_arr[3].new_val.c_val = item4->valuedouble;
            strcpy(node_arr[3].name, "temperature");

            //humidity赋值
            node_arr[4].new_val.c_val = item5->valuedouble;
            strcpy(node_arr[4].name, "humidity");
            // free(p);
            // p = NULL;
            cJSON_Delete(root);
            // }
            // else if (node.dev_type == 2)
            // {
            // }
        }
    }
    pthread_exit(NULL);
}

void *handlerr(void *arg)
{
    int acceptfd = (*(int *)arg);
    //读消息队列
    while (1)
    {
        char s[256];
        if (msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 1, 0) > 0)
        {
            printf("recv from msga type = %ld\n", recv_buf.mtype);
            printf("recv from msga data = %s\n", recv_buf.mdata);
            strcpy(s, recv_buf.mdata);
            // s = recv_buf.mdata;
            send(acceptfd, s, sizeof(s), 0);
        }
        else
        {
            perror("recv error:");
            return 0;
        }
    } pthread_exit(NULL);
}

void *handler1(void *arg)
{
    // 创建结构体数组并初始化
    struct stm32_node stm32_m[] = {
        {12, "m_ligjt", 1, 3, 0, 0, -1},
        {13, "m_heating", 1, 3, 0, 0, -1},
        {14, "m_cooling", 1, 3, 0, 0, -1},
        {15, "m_chushi", 1, 3, 0, 0, -1},
        {16, "m_buzzer", 1, 3, 0, 0, -1},
        {17, "m_temperature", 3, 3, 0, 0, -1},
        {18, "m_humidity", 3, 3, 0, 0, -1}};

    struct stm32_node node;
    char buf[128];
    int acceptfd = (*(int *)arg); // 4     5
    while (1)
    {
        int recvbyte = recv(acceptfd, buf, sizeof(buf), 0);
        if (recvbyte < 0)
        {
            perror("recv is err:");
            return NULL;
        }
        else if (recvbyte == 0)
        {
            printf("client si exit\n");
            close(acceptfd);
            break;
        }
        else
        {
            // if (node.dev_type == 1)
            // {

            printf("client: %s\n", buf);
            //从单片机获取的JSON转数据
            //反序列化json
            cJSON *root = cJSON_Parse(buf);
            if (NULL == root)
            {
                printf("parse err\n");
                return 0;
            }
            //获取root节点上的item0节点
            cJSON *item0 = cJSON_GetObjectItem(root, "m_light");
            printf("%s = %d\n", item0->string, item0->valueint);
            stm32_m[0].new_val.a_val = item0->valueint;
            //获取root节点上的item1节点
            cJSON *item1 = cJSON_GetObjectItem(root, "m_heating");
            printf("%s = %d\n", item1->string, item1->valueint);
            stm32_m[1].new_val.a_val = item1->valueint;
            //获取root节点上的item2节点
            cJSON *item2 = cJSON_GetObjectItem(root, "m_cooling");
            printf("%s = %d\n", item2->string, item2->valueint);
            stm32_m[2].new_val.a_val = item2->valueint;
            //获取root节点上的item3节点
            cJSON *item3 = cJSON_GetObjectItem(root, "m_chushi");
            printf("%s = %d\n", item3->string, item3->valueint);
            stm32_m[3].new_val.a_val = item3->valueint;
            //获取root节点上的item6节点
            cJSON *item6 = cJSON_GetObjectItem(root, "m_buzzer");
            printf("%s = %d\n", item6->string, item6->valueint);
            stm32_m[4].new_val.a_val = item6->valueint;
            //获取root节点上的item4节点
            cJSON *item4 = cJSON_GetObjectItem(root, "m_temperature");
            printf("%s = %.2f\n", item4->string, item4->valuedouble);
            stm32_m[5].new_val.c_val = item4->valuedouble;
            //获取root节点上的item5节点
            cJSON *item5 = cJSON_GetObjectItem(root, "m_humidity");
            printf("%s = %.2f\n", item5->string, item5->valuedouble);
            stm32_m[6].new_val.c_val = item5->valuedouble;

            //写共享内存

            int ret = -1;

            ret = shm_init(&para, "shm_test", MAX_NODE_SIZE);
            if (ret < 0)
            {
                struct msgbuf recv_buf;
                return 0;
            }

            void *node_p = shm_getaddr(&para);
            if (node_p == NULL)
            {
                return 0;
            }

            // 4     5
            // while (1)
            // {          //前4个字节存储实际的学生数目
            //total = (int *)node_p;
            //后面空间存储数据点
            node_arr = (struct stm32_node *)(node_p + sizeof(int));

            //*total = 3; //假设有3个人
            //light赋值
            node_arr[0].new_val.a_val = item0->valueint;
            strcpy(node_arr[0].name, "m_light");

            //heating赋值
            node_arr[1].new_val.a_val = item1->valueint;
            strcpy(node_arr[1].name, "m_heating");

            //cooling赋值
            node_arr[2].new_val.a_val = item2->valueint;
            strcpy(node_arr[2].name, "m_cooling");

            //chushi赋值
            node_arr[3].new_val.a_val = item3->valueint;
            strcpy(node_arr[3].name, "m_chushi");

            //buzzer赋值
            node_arr[4].new_val.a_val = item6->valueint;
            strcpy(node_arr[4].name, "m_chushi");

            //temperature赋值
            node_arr[5].new_val.c_val = item4->valuedouble;
            strcpy(node_arr[5].name, "m_temperature");

            //humidity赋值
            node_arr[6].new_val.c_val = item5->valuedouble;
            strcpy(node_arr[6].name, "m_humidity");
            // free(p);
            // p = NULL;
            cJSON_Delete(root);
            // }
            // else if (node.dev_type == 2)
            // {
            // }
        }
    }
    pthread_exit(NULL);
}
void *handlerr1(void *arg)
{
    int acceptfd = (*(int *)arg);
    //读消息队列
    while (1)
    {
        char s[256];
        if (msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 1, 0) > 0)
        {
            printf("recv from msga type = %ld\n", recv_buf.mtype);
            printf("recv from msga data = %s\n", recv_buf.mdata);
            strcpy(s, recv_buf.mdata);
            // s = recv_buf.mdata;
            send(acceptfd, s, sizeof(s), 0);
        }
        else
        {
            perror("recv error:");
            return 0;
        }
    } pthread_exit(NULL);
}

int main(int argc, char const *argv[])
{
    // struct REPORT recv_buf;
    //1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("sockfd is err:");
        return -1;
    }
    //2. 填充结构体
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(8878);
    saddr.sin_addr.s_addr = inet_addr("192.168.0.136");

    int len = sizeof(caddr);

    //绑定自己的ip和port
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind is err:");
        return -1;
    }
    //3/监听
    if (listen(sockfd, 5) < 0)
    {
        perror("listen is err:");
        return -1;
    }

    //1. 创建结构体数组
    struct pollfd fds[100]; //最多接受100个文件描述符
    //2.添加关心的文件描述符 并 给文件描述符设置触发方式
    fds[0].fd = sockfd;     // 标准输入
    fds[0].events = POLLIN; //读事件

    fds[1].fd = sockfd;
    fds[1].events = POLLIN;

    //3.保存数组内最后一个有效元素的下标
    int nfds = 1;

    char buf[128];
    int rett;

    while (1)
    { //printf("1111111111111111\n");
        //4.调用poll函数，检测文件描述符产生事件
        rett = poll(fds, nfds + 1, -1);
        if (rett < 0)
        {
                perror("poll is err:");
            return -1;
        }
        //printf("1\n");
        for (int i = 0; i <= nfds; i++)
        {
            if (fds[i].revents == POLLIN) //如果第三个参数被内核填充，则说明有事件响应
            {

                if (fds[i].fd == sockfd) // i  == 1
                {
                    //printf("11111/n");
                    int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
                    if (acceptfd < 0)
                    {
                        perror("accept is err:");
                        return -1;
                    }
                    if (i == 0)
                    {
                        pthread_t tid;
                        if (pthread_create(&tid, NULL, handler, &acceptfd))
                        {
                            perror("create err");
                            return 0;
                        }

                        pthread_t tidr;
                        if (pthread_create(&tidr, NULL, handlerr, &acceptfd))
                        {
                            perror("create err");
                            return 0;
                        }
                        pthread_detach(tid);
                        pthread_detach(tidr);
                    }
                    else if (i == 1)
                    {
                        pthread_t tid1;
                        if (pthread_create(&tid1, NULL, handler1, &acceptfd))
                        {
                            perror("create err");
                            return 0;
                        }

                        pthread_t tidr1;
                        if (pthread_create(&tidr1, NULL, handlerr1, &acceptfd))
                        {
                            perror("create err");
                            return 0;
                        }
                        pthread_detach(tid1);
                        pthread_detach(tidr1);
                    }
                    // //读消息队列
                    // while (1)
                    // {
                    //     char s[256];
                    //     if (msg_queue_recv("topic", &recv_buf, sizeof(recv_buf), 1, 0) > 0)
                    //     {
                    //         printf("recv from msga type = %ld\n", recv_buf.mtype);
                    //         printf("recv from msga data = %s\n", recv_buf.mdata);
                    //         strcpy(s, recv_buf.mdata);
                    //         // s = recv_buf.mdata;
                    //         send(acceptfd, s, sizeof(s), 0);
                    //     }
                    //     else
                    //     {
                    //         perror("recv error:");
                    //         return 0;
                    //     }
                    // }
                    //printf("fd: %d, ip: %s, port: %d\n", acceptfd, inet_ntoa(caddr.sin_addr),
                    //ntohs(caddr.sin_port));
                    // if (i==0)
                    // {
                    //     pthread_detach(tid);
                    // }
                    // else if (i==1)
                    // {
                    //     pthread_detach(tid1);
                    // }

                    // pthread_detach(tid);
                    nfds++; // 1  >> 2
                    fds[nfds].fd = acceptfd;
                    fds[nfds].events = POLLIN;

                    break;
                }
            }
        }
    }

    return 0;
}
